/***************************************************************************
 * This document contains confidential and proprietary information
 * subject to non-disclosure agreements with AsiaInspection. This
 * information shall not be distributed or copied without written
 * permission from the AsiaInspection.
 ***************************************************************************/
package io;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.node.ObjectNode;

/***************************************************************************
 *<PRE>
 *  Project Name    : com.allen
 *
 *  Package Name    : io
 *
 *  File Name       : FastJsonTest.java
 *
 *  Creation Date   : Nov 01, 2016
 *
 *  Author          : Allen Zhang
 *
 *  Purpose         : TODO
 *
 *
 *  History         : TODO
 *
 *</PRE>
 ***************************************************************************/

public class FastJsonTest {

	public static void main(String args[]) throws IOException {
		String content = new String(Files.readAllBytes(Paths.get("D://test.json")));
//		System.out.println(content);

		OrderGeneralInfoBean bigObj = JSON.parseObject(content, OrderGeneralInfoBean.class);
		System.out.println("----------- big object: book from -----------" + bigObj.getBookFromPreOrder());
		System.out.println("----------- big object: book date -----------" + bigObj.getBookingDate());
		System.out.println("big json: " + JSON.toJSONString(bigObj, SerializerFeature.WriteMapNullValue));

		ApiOrderGeneralInfoBean smallObj = JSON.parseObject(content, ApiOrderGeneralInfoBean.class);
		System.out.println("----------- update in small object -----------" + smallObj.getBookFromPreOrder());
		//update to new value in small json
		smallObj.setBookFromPreOrder("888888888888888888");
		System.out.println("----------- small object: book from -----------" + smallObj.getBookFromPreOrder());
		String smallJson = JSON.toJSONString(smallObj, SerializerFeature.WriteMapNullValue);

		//final step: to update big json with small json
		ObjectMapper objectMapper = new ObjectMapper();
		ObjectReader updater = objectMapper.readerForUpdating(bigObj);
		OrderGeneralInfoBean updatedBigObj = updater.readValue(smallJson);

		System.out.println("----------- big object after update: book from  -----------" + updatedBigObj.getBookFromPreOrder());
		System.out.println("----------- big object after update: book date -----------" + updatedBigObj.getBookingDate());
		System.out.println("big json after update: " + JSON.toJSONString(updatedBigObj, SerializerFeature.WriteMapNullValue));
	}

	public static JsonNode merge(JsonNode mainNode, JsonNode updateNode) {

		Iterator<String> fieldNames = updateNode.fieldNames();
		while (fieldNames.hasNext()) {

			String fieldName = fieldNames.next();
			JsonNode jsonNode = mainNode.get(fieldName);
			// if field exists and is an embedded object
			if (jsonNode != null && jsonNode.isObject()) {
				merge(jsonNode, updateNode.get(fieldName));
			}
			else {
				if (mainNode instanceof ObjectNode) {
					// Overwrite field
					JsonNode value = updateNode.get(fieldName);
					((ObjectNode) mainNode).put(fieldName, value);
				}
			}

		}

		return mainNode;
	}
}
